﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace QuickPasteItLib
{
    class HttpTools
    {
        /// <summary>
        /// Performs the detailed HTTP request.
        /// </summary>
        /// <param name="uri">The URI for the request.</param>
        /// <param name="reqParams">The data for the request.</param>
        /// <param name="reqType">Whether to send a GET or POST request.</param>
        /// <param name="autoRedirect">If true, redirects in HTTP responses will be followed.</param>
        /// <returns>The HTTP response on success, an empty response on failure.</returns>
        public static WebResponse HttpRequest(string uri, string reqParams = "", HttpReqType reqType = HttpReqType.POST, bool autoRedirect = false)
        {
            try
            {
                HttpWebRequest httpWReq = (HttpWebRequest) WebRequest.Create(uri);
                httpWReq.Method = "GET";
                UTF8Encoding encoding = new UTF8Encoding();
                string postData = reqParams;
                httpWReq.Accept = "*/*";
                httpWReq.UserAgent = "QuickPasteIt";
                httpWReq.AllowAutoRedirect = autoRedirect;

                // If we're posting, we need to emulate curl -F
                if (reqType == HttpReqType.POST)
                {
                    httpWReq.Method = "POST";
                    var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
                    httpWReq.ContentType = "multipart/form-data; boundary=" + boundary;

                    postData = "";

                    var reqParamsCollection = HttpUtility.ParseQueryString(reqParams);

                    if (reqParamsCollection.Count > 0)
                    {
                        var reqParamsCollectionFlat = reqParamsCollection.AllKeys.SelectMany(reqParamsCollection.GetValues, (k, v) => new { key = k, value = v });
                        foreach (var paramset in reqParamsCollectionFlat)
                        {
                            postData += "--" + boundary + "\r\n";                            
                            postData += "Content-Disposition: form-data; name=\"" + paramset.key + "\"\r\n\r\n";
                            postData += paramset.value + "\r\n";
                        }
                        postData += "--" + boundary + "--\r\n";
                    }
                }

                byte[] data = encoding.GetBytes(postData);
                httpWReq.ContentLength = data.Length;

                // Write request
                using (Stream newStream = httpWReq.GetRequestStream())
                    newStream.Write(data, 0, data.Length);

                // Receive response
                return httpWReq.GetResponse();
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Fetches the HTTP response data as a string.
        /// </summary>
        /// <returns>The HTTP response data as a string on success, an empty string on failure.</returns>
        public static string GetResponseString(WebResponse response)
        {
            try
            {
                return new StreamReader(response.GetResponseStream()).ReadToEnd().Trim();
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// Fetches the redirect location from the given response, if applicable.
        /// </summary>
        /// <returns>An empty string on failure, the redirect location on success.</returns>
        public static string GetRedirectLocationFromResponse(WebResponse response)
        {
            try
            {
                return response.Headers.Get("Location");
            }
            catch
            {
                return "";
            }
        }

        public enum HttpReqType
        {
            POST,
            GET
        }
    }
}
